package org.common.utils.thread.entry;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Supplier;

/**
 * 线程实体池
 * @author zhouzhibing
 * @date 2025/11/21 17:56
 */
public class ThreadEntryPool<T> {

    /**
     * 检查超时间隔
     */
    private static final int CHECK_TIME_OUT_GAP = 5000;
    /**
     * 超时时间
     */
    private final int timeout;
    /**
     * 最后检查时间
     */
    private long lastCheckTime;
    /**
     * 空闲的集合
     */
    private final Map<Long , Entry<T>> freeMap;
    /**
     * 使用中的集合
     */
    private final Map<Long , Entry<T>> processMap;
    /**
     * 创建线程实体函数
     */
    private final Supplier<T> createEntryFunc;

    /**
     * 构造函数
     * @param timeout 超时时间
     * @param createEntryFunc 创建线程实体函数
     */
    public ThreadEntryPool(int timeout , Supplier<T> createEntryFunc) {
        this.timeout = timeout;
        this.createEntryFunc = createEntryFunc;

        this.freeMap = new ConcurrentHashMap<>();
        this.processMap = new ConcurrentHashMap<>();
    }

    /**
     * 新建线程实体
     * @return 线程实体
     */
    private Entry<T> newEntry() {
        T t = createEntryFunc.get();
        return new Entry<>(t);
    }

    /**
     * 获取线程实体
     * @return 线程实体
     */
    public T getEntry() {
        long threadId = Thread.currentThread().threadId();
        Entry<T> entry = freeMap.remove(threadId);
        if (entry == null) {
            entry = newEntry();
        }
        processMap.put(threadId , entry);
        T t = entry.get();
        checkTimeout();
        return t;
    }

    /**
     * 归还线程实体
     */
    public void returnEntry() {
        long threadId = Thread.currentThread().threadId();
        Entry<T> entry = processMap.remove(threadId);
        if (entry == null) {
            return;
        }
        freeMap.put(threadId , entry);
    }

    /**
     * 检查超时
     */
    private void checkTimeout() {
        long currentTime = System.currentTimeMillis();
        long checkTimeGap = currentTime - lastCheckTime;
        //如果间隔时间小于5000毫秒，则不检查
        if (checkTimeGap < CHECK_TIME_OUT_GAP) {
            return;
        }

        checkTimeout(currentTime, freeMap);
        checkTimeout(currentTime, processMap);

        lastCheckTime = System.currentTimeMillis();
    }

    /**
     * 检查超时
     * @param map 集合
     */
    private void checkTimeout(long currentTime , Map<Long , Entry<T>> map) {
        Iterator<Entry<T>> iterator = map.values().iterator();
        while (iterator.hasNext()) {
            Entry<T> entry = iterator.next();
            long gapTime = currentTime - entry.getLastUseTime();
            if (gapTime > timeout) {
                iterator.remove();
            }
        }
    }


    @Override
    public String toString() {
        return "ThreadEntryPool{" +
                "timeout=" + timeout +
                ", lastCheckTime=" + lastCheckTime +
                ", freeMapCount=" + freeMap.size() +
                ", processMapCount=" + processMap.size() +
                '}';
    }

    /**
     * 线程实体
     * @param <T> 实体类型
     */
    private static class Entry<T> {
        /**
         * 实体
         */
        private final T entry;
        /**
         * 最后使用时间
         */
        private long lastUseTime;

        public Entry(T entry) {
            this.entry = entry;
            this.lastUseTime = System.currentTimeMillis();
        }

        public T get() {
            this.lastUseTime = System.currentTimeMillis();
            return entry;
        }

        public long getLastUseTime() {
            return lastUseTime;
        }
    }
}
